﻿using System.Web;
using RazorEngine;
using System.Collections.Specialized;
using System.Net.Mail;
using System.Net;
using System;
using MMITWeb.Infrastructure.Abstract;
using System.Text;
using System.Collections.Generic;
using MMITCore.Logging;
using System.IO;
using MMITCore.Abstract;
using MMITWeb.Models;
using System.Web.Configuration;
using System.Web.Mvc;
using MMITWeb.Infrastructure.Extensions;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace MMITWeb.Infrastructure.Concrete
{
    public class NotificationManager : INotificationManager
    {
        private HttpContext _context = null;
        private SmtpClient _mailclient = null;
        private MailMessage _msg = null;
        ILogger<SynkronLogger> _logger;
        private NotificationType notificationType;
        private WebClient clickatellClient;
        string clickatellBaseURL = string.Empty;
        ITemplatePath _templatePath;
        public NotificationType _notificationType
        {
            get 
            { 
                return notificationType; 
            }
            set 
            {
                notificationType = value; 
                switch (_notificationType)
                {
                    case NotificationType.EmailNotification:
                        {
                            try
                            {
                                //initialize email settings...
                                _mailclient = new SmtpClient(WebConfigurationManager.AppSettings["smtpserver"], int.Parse(WebConfigurationManager.AppSettings["smtpport"]));
                                _mailclient.DeliveryMethod = SmtpDeliveryMethod.Network;
                                _mailclient.UseDefaultCredentials = false;
                                _mailclient.Credentials = new NetworkCredential(WebConfigurationManager.AppSettings["smtpUsername"], WebConfigurationManager.AppSettings["smtpPassword"]);
                                _mailclient.EnableSsl = true;

                                ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate,X509Chain chain, 
                                    SslPolicyErrors sslPolicyErrors) { 
                                        return true; 
                                };

                                _logger.WriteInformation(60000007, () => string.Format("Email Settings Initialized Successfully"),
                                        new Dictionary<string, object> { { string.Format("mailclient"), _logger.Desc(_mailclient) } });
                            }
                            catch (Exception Ex)
                            {
                                _logger.WriteCritical(60000008, () => "Email Settings Initialization Failure", Ex,
                                    new Dictionary<string, object> { { string.Format("SMTP Info: "), _logger.Desc(this) } });
                            }
                        }
                        break;
                    //initialize sms gateways settings.....
                    case NotificationType.SMSNotification:
                        {
                            try 
	                        {	        
		                        clickatellBaseURL = WebConfigurationManager.AppSettings["smsgatewaybaseurl"];
                                // Add a user agent header in case the requested URI contains a query.s
                                clickatellClient = new WebClient();
                                clickatellClient.Headers.Add ("user-agent", "Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                                clickatellClient.QueryString.Add("user", WebConfigurationManager.AppSettings["smsUsername"]);
                                clickatellClient.QueryString.Add("password", WebConfigurationManager.AppSettings["smsPassword"]);
                                clickatellClient.QueryString.Add("api_id", WebConfigurationManager.AppSettings["smsAPIID"]);
                                clickatellClient.QueryString.Add("from", WebConfigurationManager.AppSettings["appname"]);

                                _logger.WriteInformation(60000009, () => string.Format("SMS Gateway Initialized Successfully"),
                                    new Dictionary<string, object> { { string.Format("SMS Gateway Info: "), _logger.Desc(clickatellClient) } });
	                        }
	                        catch (Exception Ex)
	                        {
                                _logger.WriteCritical(60000010, () => "SMS Gateway Initialization Failure", Ex,
                                     new Dictionary<string, object> { { string.Format("SMS Gateway Info :"), _logger.Desc(clickatellClient) } });
	                        }
                        }

                        break;

                }
            }
        }

        public NotificationManager(ILogger<SynkronLogger> logger, ITemplatePath templatePath) 
        {
            _logger = logger;
            _templatePath = templatePath;
        }

        #region INotificationManager Members

        public void SendTemplateEmail(EmailType emailType,EmailViewModel model)
        {   
            MailAddressCollection toList = new MailAddressCollection();
            MailAddress recipientAddress = null;
            MailAddress fromAddress = new MailAddress(model.from, string.IsNullOrEmpty(model.from_alias) ? model.from : model.from_alias);
            foreach (string toAddress in model.to)
            {
                recipientAddress = new MailAddress(toAddress);
                toList.Add(recipientAddress);
            }
            _msg = new MailMessage(fromAddress, toList[0]);
            _msg.BodyEncoding = System.Text.Encoding.UTF8;
            _msg.SubjectEncoding = System.Text.Encoding.UTF8;
            
            for (int i = 1; i < toList.Count; i++)
            {
                _msg.CC.Add(toList[i]);
            }

            _msg.Subject = model.subject;
            _msg.SubjectEncoding = System.Text.Encoding.UTF8;
            _msg.IsBodyHtml = true;

            try
            {

                var htmlMessage = EmailFactory.ParseTemplate<EmailViewModel>(model, _templatePath.TemplatePath, emailType);
                _msg.Body = htmlMessage;
                _mailclient.Send(_msg);
                
                _logger.WriteInformation(6000000, () => string.Format("Template Email Sent to : {0}| Subject : {1}", model.to.ToString(), model.subject),
                    new Dictionary<string, object> { { string.Format("Mail Message"), _logger.Desc(_msg) } });
            }
            catch (Exception Ex)
            {

                //Log Exception...
                _logger.WriteError(6000001, () => string.Format("Exception Sending Template Email"), Ex,
                   new Dictionary<string, object> { { string.Format("Mail Message"), _logger.Desc(_msg) }
                   });
            }
        }
        public void SendPlainEmail(string[] to, string from, string from_alias, string subject, string content)
        {
            MailAddressCollection toList = new MailAddressCollection();
            MailAddress recipientAddress = null;
            MailAddress fromAddress = new MailAddress(from, string.IsNullOrEmpty(from_alias) ? from : from_alias);
            foreach (string toAddress in to)
            {
                recipientAddress = new MailAddress(toAddress);
                toList.Add(recipientAddress);
            }
            _msg = new MailMessage(fromAddress, toList[0]);
            _msg.BodyEncoding = System.Text.Encoding.UTF8;
            _msg.SubjectEncoding = System.Text.Encoding.UTF8;
            for (int i = 1; i < toList.Count; i++)
            {
                _msg.CC.Add(toList[i]);
            }

            _msg.Subject = subject;
            _msg.SubjectEncoding = System.Text.Encoding.UTF8;
            _msg.IsBodyHtml = false;
            _msg.Body = content;

            try
            {
                _mailclient.Send(_msg);

                _logger.WriteInformation(6000002, () => string.Format("Plain Email Sent to : {0}| Subject : {1}  | Message : {2}", to.ToString(), subject, content),
                    new Dictionary<string, object> { { string.Format("Mail Message"), _logger.Desc(_msg) } });
            }
            catch (Exception Ex){

                //Log Exception...
                _logger.WriteError(6000003, () => string.Format("Exception Sending Plain Email Formatted"), Ex,
                   new Dictionary<string, object> { { string.Format("Mail Message"), _logger.Desc(_msg) }
                   });
            }

        }

        //plugin to sms gateway..
        public void SendShortMessage(string strTo, string strMessage)
        {
            clickatellClient.QueryString.Add("to", strTo);
            clickatellClient.QueryString.Add("text", strMessage);
            Stream data = clickatellClient.OpenRead(this.clickatellBaseURL);
            StreamReader reader = new StreamReader(data);
            try
            {
                string s = reader.ReadToEnd();
                data.Close();
                reader.Close();

                _logger.WriteInformation(6000004, () => string.Format("Short Message sent sucessfully to {0}", strTo),
                    new Dictionary<string, object> { { string.Format("Mail Message"), _logger.Desc(s) } 
                    });
            }
            catch (OutOfMemoryException Ex)
            {
                //Log Exception...
                _logger.WriteError(6000005, () => string.Format("Out of Memory calling Short Message Gateway : "), Ex,
                   new Dictionary<string, object> { { string.Format("Short Message"), _logger.Desc(strMessage) }
                   });
            }
            catch (IOException Ex)
            {
                //Log Exception...
                _logger.WriteError(6000006, () => string.Format("Gateway I/O Exception : "), Ex,
                   new Dictionary<string, object> { { string.Format("Short Message"), _logger.Desc(strMessage) }
                   });
            }
        }
        #endregion
    }

    public enum NotificationType
    {
        EmailNotification = 1,
        SMSNotification = 2
    }

    //not sure what this enum will be used for just yet...
    public enum EmailType
    {
        _Registration, 
        _ProfileUpdate, 
        _PasswordReset, 
        _PasswordUpdate, 
        _LoadWallet, 
        _SendMoney
    }

    public static class EmailFactory
    {

        public static string ParseTemplate<T>(T model, string pathToTemplates, EmailType emailType)
        {
            var templatePath = string.Format(@"{0}{1}", pathToTemplates , string.Format("{0}.cshtml", emailType));
            var content = File.ReadAllText(templatePath);

            return Razor.Parse(content, model);
        }
    }
}